package io.renren.common.weixin.payutils;


import io.renren.common.utils.HttpClient;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.Map.Entry;

/**
 * Created by whc on 2016/3/23.
 */
public class WeiXinSignAndPackage {

    //编码
    private static String inputCharset="UTF-8";

    /**
     * 创建支付包Package
     * @param treeMap
     * @return
     */
    public static String createPackage(TreeMap<String,String> treeMap,String paternerKey){
        String string1=originalString(treeMap);
        String stringSignTemp = string1 + "key="+paternerKey;
        String sign=MD5Util.MD5Encode(stringSignTemp, inputCharset).toUpperCase();
        return sign;
    }

    /**
     * 创建支付签名paysign
     * @param
     * @return
     */
    public static String createPaySign(TreeMap<String,String> param,String paternerKey){
        String string1=originalString(param);
        String stringSignTemp = string1 + "key="+paternerKey;
        System.out.println("签名调试输出："+stringSignTemp);
        String paysign=MD5Util.MD5Encode(stringSignTemp, inputCharset).toUpperCase();
        return paysign;
    }

    /**
     * wxpackage组装原始串
     * @param treeMap
     * @return
     */
    private static String originalString(TreeMap<String,String> treeMap){
        Set<Entry<String, String>> entry = treeMap.entrySet();
        StringBuffer sb = new StringBuffer();
        for(Entry<String,String> obj : entry){
            String k = obj.getKey();
            String v = obj.getValue();
            if(v == null && v.equals(""))
                continue;
            sb.append(k+"="+v+"&");
        }
        return sb.toString();
    }

    private static String originalURLString(TreeMap<String,String> treeMap){
        Set<Entry<String, String>> entry = treeMap.entrySet();
        StringBuffer sb = new StringBuffer();
        try {
            for (Entry<String, String> obj : entry) {
                String k = obj.getKey();
                String v = obj.getValue();
                if (v == null && v.equals(""))
                    continue;
                sb.append(k.toLowerCase() + "=" + URLEncoder.encode(v, inputCharset) + "&");
            }
        } catch (Exception e) {
            // TODO: handle exception
        }
        return sb.toString();
    }

    /**
     * 创建微信支付订单号
     * @return
     */
    public static String getOutTradeNo(){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddhhmmss");
        String body= String.valueOf((int) (Math.random() * 100000000));
        String outTradeNo="WXP"+sdf.format(new Date())+body;
        System.out.println("创建支付订单号："+outTradeNo);
        return outTradeNo;
    }

    /**
     * 创建格式为yyyyMMddHHmmss的当前时间串
     * @return
     */
    public static String getNowTime(){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        return sdf.format(new Date());
    }

    /**
     * 是否财付通签名,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。
     */
    public synchronized static boolean isValidSign(TreeMap<String,String> treeMap,String paternerKey){
        Set<Entry<String, String>> entry = treeMap.entrySet();
        StringBuffer sb = new StringBuffer();
        String signback = null;
        String input_charset=null;
        for(Entry<String,String> obj : entry){
            String k = obj.getKey();
            String v = obj.getValue();
            if(v == null && v.equals(""))
                continue;
            if(k.equals("sign")){
                signback = v;
                continue;
            }
            sb.append(k.toLowerCase()+"="+v+"&");
        }
        String string1=sb.toString();
        String stringSignTemp = string1 + "key="+paternerKey;
        System.out.println("程序计算签名串："+stringSignTemp);
        String sign=MD5Util.MD5Encode(stringSignTemp, input_charset).toUpperCase();
        System.out.println("程序计算财付通签名："+sign);
        System.out.println("系统返回签名："+signback);
        if(sign.equals(signback)){
            System.out.println("DeBug财付通签名比对结果：TRUE");
            return true;
        }else{
            System.out.println("DeBug财付通签名比对结果：FALSE");
            return false;
        }
    }

    /**
     * 判断微信签名
     * @param treeMap
     * @return
     */
    public synchronized static boolean isWXSign(TreeMap<String,String> treeMap){
        Set<Entry<String, String>> entry = treeMap.entrySet();
        StringBuffer sb = new StringBuffer();
        String appSignature = null;
        for(Entry<String,String> obj : entry){
            String k = obj.getKey();
            String v = obj.getValue();
            if(v == null && v.equals(""))
                continue;
            if(k.equals("AppSignature")){
                appSignature = v;
                continue;
            }
            if(k.equals("SignMethod")){
                continue;
            }
            sb.append(k.toLowerCase()+"="+v+"&");
        }
        String paysign = sb.toString();
        paysign = paysign.substring(0, paysign.length()-1);
        System.out.println("\n\n程序计算微信签名串："+paysign);
        paysign = Sha1Util.getSha1(paysign);
        System.out.println("程序计算微信签名结果："+paysign);
        System.out.println("微信返回签名结果："+appSignature);
        if(paysign.equals(appSignature)){
            System.out.println("DeBug微信签名比对结果：TRUE");
            return true;
        }else{
            System.out.println("DeBug微信签名比对结果：FALSE");
            return false;
        }
    }

    public static TreeMap<String,String> mapToTreeMap(Map<Object,Object> map){
        TreeMap<String, String> treeMap = new TreeMap<String, String>();
        Set<Entry<Object, Object>> entry = map.entrySet();
        for (Entry<Object, Object> key : entry) {
            treeMap.put(key.getKey().toString(), ((String[])key.getValue())[0].toString());
        }
        return treeMap;
    }

    public static TreeMap<String,String> strmapToTreeMap(Map<String,String> map){
        TreeMap<String, String> treeMap = new TreeMap<String, String>();
        Set<Entry<String, String>> entry = map.entrySet();
        for (Entry<String, String> key : entry) {
            treeMap.put(key.getKey().toString(), key.getValue().toString());
        }
        return treeMap;
    }

    public static String getPrepayId(TreeMap<String, String> payParamMap,String prepayIdUrl){
        StringBuffer buffer = new StringBuffer();
        buffer.append("<xml>");
        if (payParamMap != null && !payParamMap.isEmpty()) {
            for (Entry<String, String> entry : payParamMap.entrySet()) {
                if(entry.getKey().equals("attach") || entry.getKey().equals("body") || entry.getKey().equals("sign")){
                    buffer.append("<"+entry.getKey()+">");
                    buffer.append("<![CDATA["+entry.getValue()+"]]>");
                    buffer.append("</"+entry.getKey()+">");
                }else{
                    buffer.append("<"+entry.getKey()+">");
                    buffer.append(entry.getValue());
                    buffer.append("</"+entry.getKey()+">");
                }
            }
        }
        buffer.append("</xml>");
        System.out.println(buffer.toString());
        String result= new HttpClient().sendPost(prepayIdUrl, buffer.toString());
        return result;
    }


    //企业付款接口
    public static String transfers(String cert,String pass,TreeMap<String, String> payParamMap,String url){
        StringBuffer buffer = new StringBuffer();
        buffer.append("<xml>");
        if (payParamMap != null && !payParamMap.isEmpty()) {
            for (Entry<String, String> entry : payParamMap.entrySet()) {
                if(entry.getKey().equals("re_user_name") || entry.getKey().equals("desc") || entry.getKey().equals("sign")){
                    buffer.append("<"+entry.getKey()+">");
                    buffer.append("<![CDATA["+entry.getValue()+"]]>");
                    buffer.append("</"+entry.getKey()+">");
                }else{
                    buffer.append("<"+entry.getKey()+">");
                    buffer.append(entry.getValue());
                    buffer.append("</"+entry.getKey()+">");
                }
            }
        }
        buffer.append("</xml>");

        String xmlStr = "";
        try {
            xmlStr = new String(buffer.toString().getBytes(), "ISO8859-1");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

//        System.out.println(buffer.toString());
//        String result= new HttpClient().sendSSLPost(cert, pass, url, xmlStr);
        return "";
    }


    // 获得js signature
    public static String getSignature(String jsapi_ticket, String timestamp,
                               String nonce, String jsurl) throws IOException {
        /****
         * 对 jsapi_ticket、 timestamp 和 nonce 按字典排序 对所有待签名参数按照字段名的 ASCII
         * 码从小到大排序（字典序）后，使用 URL 键值对的格式（即key1=value1&key2=value2…）拼接成字符串
         * string1。这里需要注意的是所有参数名均为小写字符。 接下来对 string1 作 sha1 加密，字段名和字段值都采用原始值，不进行
         * URL 转义。即 signature=sha1(string1)。
         * **如果没有按照生成的key1=value&key2=value拼接的话会报错
         */
        String[] paramArr = new String[] { "jsapi_ticket=" + jsapi_ticket,
                "timestamp=" + timestamp, "noncestr=" + nonce, "url=" + jsurl };
        Arrays.sort(paramArr);
        // 将排序后的结果拼接成一个字符串
        String content = paramArr[0].concat("&"+paramArr[1]).concat("&"+paramArr[2])
                .concat("&"+paramArr[3]);
        System.out.println("拼接之后的content为:"+content);
        String gensignature = null;
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-1");
            // 对拼接后的字符串进行 sha1 加密
            byte[] digest = md.digest(content.toString().getBytes());
            gensignature = byteToStr(digest);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        // 将 sha1 加密后的字符串与 signature 进行对比
        if (gensignature != null) {
            return gensignature;// 返回signature
        } else {
            return "false";
        }
        // return (String) (ciphertext != null ? ciphertext: false);
    }

    /**
     * 将字节数组转换为十六进制字符串
     *
     * @param byteArray
     * @return
     */
    private static String byteToStr(byte[] byteArray) {
        String strDigest = "";
        for (int i = 0; i < byteArray.length; i++) {
            strDigest += byteToHexStr(byteArray[i]);
        }
        return strDigest;
    }

    /**
     * 将字节转换为十六进制字符串
     *
     * @param mByte
     * @return
     */
    private static String byteToHexStr(byte mByte) {
        char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A',
                'B', 'C', 'D', 'E', 'F' };
        char[] tempArr = new char[2];
        tempArr[0] = Digit[(mByte >>> 4) & 0X0F];
        tempArr[1] = Digit[mByte & 0X0F];
        String s = new String(tempArr);
        return s;
    }

}


